import logging
from typing import List

from fastapi import HTTPException
from tortoise.transactions import atomic

from app.core.crud import CRUDBase
from app.models.admin import Api, Menu, Role
from app.schemas.roles import RoleCreate, RoleUpdate


log = logging.getLogger(__name__)


class RoleController(CRUDBase[Role, RoleCreate, RoleUpdate]):
    def __init__(self):
        super().__init__(model=Role)

    async def is_exist(self, name: str) -> bool:
        return await self.model.filter(name=name).exists()

    @atomic()
    async def create_role(self, role_in: RoleCreate):
        """
        创建角色
        """
        # 检查角色名称是否已存在
        if await self.is_exist(name=role_in.name):
            raise HTTPException(
                status_code=400,
                detail=f"角色名称 '{role_in.name}' 已存在"
            )

        # 创建角色
        role_obj = await self.create(obj_in=role_in)

        # 处理权限关联
        if role_in.permissions:
            menu_objects = await Menu.filter(id__in=role_in.permissions).all()
            await role_obj.menus.add(*menu_objects)

        log.info(f"角色[{role_in.code}]创建成功，权限列表: {role_in.permissions}")


    @atomic()
    async def update_role(self, role_in: RoleUpdate):
        """
        更新角色
        """
        if not role_in.id:
            raise HTTPException(status_code=400, detail="角色ID不能为空")

        # 检查角色是否存在
        role_obj = await role_controller.get(id=role_in.id)
        if not role_obj:
            raise HTTPException(status_code=404, detail="角色不存在")

        # 更新角色
        await role_controller.update(id=role_in.id, obj_in=role_in)

        # 处理权限关联
        if role_in.permissions:
            menu_objects = await Menu.filter(id__in=role_in.permissions).all()
            await role_obj.menus.clear()
            await role_obj.menus.add(*menu_objects)

        log.info(f"角色[{role_obj.code}]修改成功，权限列表: {role_in.permissions}")


    async def update_roles(self, role: Role, menu_ids: List[int], api_infos: List[dict]) -> None:
        await role.menus.clear()
        for menu_id in menu_ids:
            menu_obj = await Menu.filter(id=menu_id).first()
            await role.menus.add(menu_obj)

        await role.apis.clear()
        for item in api_infos:
            api_obj = await Api.filter(path=item.get("path"), method=item.get("method")).first()
            await role.apis.add(api_obj)


    @atomic()
    async def remove(self, id: int) -> None:
        # 删除角色
        role = await self.get(id=id)
        await role.delete()

        # 删除角色关联的菜单
        await role.menus.clear()

        # 删除角色关联的API
        await role.apis.clear()

role_controller = RoleController()
